package com.jcgyl.export.controller;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.quartz.JobDataMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.sql2o.Connection;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jcgyl.export.config.QuartzConfig;
import com.jcgyl.export.dao.CustomerDao;
import com.jcgyl.export.dao.TbdictionaryDao;
import com.jcgyl.export.dao.TbedpinfoDao;
import com.jcgyl.export.dao.TblogisticDao;
import com.jcgyl.export.dao.TbuploadDetailDao;
import com.jcgyl.export.dao.TbuploadinfoDao;
import com.jcgyl.export.entity.Customer;
import com.jcgyl.export.entity.Tbdictionary;
import com.jcgyl.export.entity.Tbedpinfo;
import com.jcgyl.export.entity.Tblogisticinfo;
import com.jcgyl.export.entity.Tbuploaddetail;
import com.jcgyl.export.entity.Tbuploadinfo;
import com.jcgyl.export.mapper.TbInventoryBodyMapper;
import com.jcgyl.export.mapper.TbInventoryHeadMapper;
import com.jcgyl.export.mapper.TbedpinfoMapper;
import com.jcgyl.export.mapper.TblogisticinfoMapper;
import com.jcgyl.export.mapper.TborderheadMapper;
import com.jcgyl.export.mapper.TborderlistMapper;
import com.jcgyl.export.mapper.TbpayinfoMapper;
import com.jcgyl.export.mapper.TbuploaddetailMapper;
import com.jcgyl.export.mapper.TbuploadinfoMapper;
import com.jcgyl.export.mapper.TbwaybillMapper;
import com.jcgyl.export.model.BaseResponseModel;
import com.jcgyl.export.model.GenerateParameter;
import com.jcgyl.export.model.PagerResponseModel;
import com.jcgyl.export.model.SocketMessage;
import com.jcgyl.export.model.UploadQueryModel;
import com.jcgyl.export.mq.MessageSender;
import com.jcgyl.export.service.Impl.InventoryServiceImpl;
import com.jcgyl.export.service.Impl.OrderServiceImpl;
import com.jcgyl.export.service.Impl.PayInfoServiceImpl;
import com.jcgyl.export.service.Impl.WaybillServiceImpl;
import com.jcgyl.export.util.MyDao;
import com.jcgyl.export.util.ParseExcelUtil;
import com.jcgyl.export.websocket.ProcessWebSocketHandler;

@Controller
@RequestMapping("/order")
public class OrderController {
	@Value(value = "classpath:excel.xml")
	private Resource excelXml;
	@Autowired
	private TbdictionaryDao tbdictionaryDao;
	@Autowired
	private TblogisticDao tblogisticDao;
	@Autowired
	private TbedpinfoDao tbedpinfoDao;
	@Autowired
	private TbuploadinfoMapper tbuploadinfoMapper;
	@Autowired
	private TbuploadDetailDao tbuploadDetailDao;
	@Autowired
	private TbedpinfoMapper tbedpinfoMapper;
	@Autowired
	private TbuploaddetailMapper tbuploaddetailMapper;
	@Autowired
	private TbpayinfoMapper tbpayinfoMapper;
	@Autowired
	private TborderheadMapper tborderheadMapper;
	@Autowired
	private TborderlistMapper tborderlistMapper;
	@Autowired
	private TbwaybillMapper tbwaybillMapper;
	@Autowired
	private MessageSender messageSender;
	@Autowired
	private TblogisticinfoMapper tblogisticinfoMapper;
	@Autowired
	private TbInventoryHeadMapper tbinventoryheadMapper;
	@Autowired
	private TbInventoryBodyMapper tbinventorybodyMapper;
	@Autowired
	private CustomerDao customerDao;
	@Autowired
	private WaybillServiceImpl waybillServiceImpl;
	@Autowired
	private InventoryServiceImpl inventoryServiceImpl;
	@Autowired
	private OrderServiceImpl orderServiceImpl;
	@Autowired
	private PayInfoServiceImpl payInfoServiceImpl;
	@Autowired
	private TbuploadinfoDao tbuploadinfoDao;

	@GetMapping()
	public String Index(Model model) {
		// 绑定数据
		model.addAttribute("messages", null);
		return "index";
	}

	@GetMapping("/cancel")
	public String CancelTask(int uploadId) {
		return "order/upload";
	}

	@GetMapping("/query")
	public String Query() {
		return "order/query";
	}

	@ResponseBody
	@GetMapping("/uploads")
	public List<Tbuploadinfo> GetLatestUploads() {
		List<Tbuploadinfo> uploads = new ArrayList<Tbuploadinfo>();
		uploads = tbuploadinfoDao.GetLatestUploads(5);
		return uploads;
	}

	@GetMapping("/import")
	public ModelAndView Import() {
		List<Customer> customers = customerDao.findAllCustomer(null, null, null, null, null, 0, 100);
		List<Tbedpinfo> edps = tbedpinfoDao.findAllEdpinfos();
		List<Tbedpinfo> edp_infos = edps.stream().filter(w -> w.getEdpType().equals(1)).collect(Collectors.toList());
		List<Tbedpinfo> platform_infos = edps.stream().filter(w -> w.getEdpType().equals(0))
				.collect(Collectors.toList());
		List<Tbdictionary> dictionaries = tbdictionaryDao.findAllDictionaries();
		List<Tbdictionary> ciq_ports = dictionaries.stream().filter(w -> w.getTypeid().equals("APPLYPORTINSP"))
				.collect(Collectors.toList());
		List<Tbdictionary> jcb_ports = dictionaries.stream().filter(w -> w.getTypeid().equals("JCBORDERPORTINSP"))
				.collect(Collectors.toList());
		edp_infos.sort((p1, p2) -> p2.getEdpId().compareTo(p1.getEdpId()));
		platform_infos.sort((p1, p2) -> p2.getEdpId().compareTo(p1.getEdpId()));
		List<Tblogisticinfo> logistics = tblogisticDao.findAllLogisticinfos();
		ModelAndView mav = new ModelAndView("order/import");
		mav.addObject("customers", customers);
		mav.addObject("edp_infos", edp_infos);
		mav.addObject("platforms", platform_infos);
		mav.addObject("ciq_ports", ciq_ports);
		mav.addObject("jcb_ports", jcb_ports);
		mav.addObject("logistics", logistics);
		return mav;
		// return new ModelAndView("order/import", "model", model);
		// return "order/import";
	}

	/*
	 * 上传的excel进行解析，主要包括 1.必填项验证 2.数据有效性验证
	 * 
	 */
	@GetMapping("/process")
	@ResponseBody
	public BaseResponseModel ProcessOrder(int uploadId) throws JsonProcessingException, IOException {
		BaseResponseModel model = new BaseResponseModel();
		Tbuploadinfo upload = tbuploadinfoMapper.selectByPrimaryKey(uploadId);
		File excelFile = new File(upload.getFilePath());
		File xmlFile = excelXml.getFile();
		// File xmlFile = ResourceUtils.getFile("classpath:excel.xml");
		try {
			ParseExcelUtil utility = new ParseExcelUtil(excelFile, xmlFile, upload.getUploadId());
			StringBuffer errorString = utility.getErrorString();
			if (errorString != null && errorString.length() > 0) {
				model.setIsError(true);
				model.setMessage(errorString.toString());
			}
			utility.setErrorString(new StringBuffer());
			int count = utility.listDatas.size();
			tbuploadinfoDao.UpdateUploadInfoCount(count, uploadId);
			SocketMessage message = new SocketMessage();
			message.messageType = "refresh";
			ObjectMapper objectMapper = new ObjectMapper();
			ProcessWebSocketHandler.sendInfo(objectMapper.writeValueAsString(message));
		} catch (Exception ex) {
			model.setIsError(true);
			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw);
			ex.printStackTrace(pw);
			String sStackTrace = sw.toString(); // stack trace as a string
			model.setMessage(sStackTrace);
		}
		return model;
	}

	@PostMapping("/send")
	@ResponseBody
	public BaseResponseModel Send(@RequestBody GenerateParameter parameter) {
		BaseResponseModel model = new BaseResponseModel();
		try {
			JobDataMap map = new JobDataMap();
			map.put("inventoryServiceImpl", inventoryServiceImpl);
			map.put("orderServiceImpl", orderServiceImpl);
			map.put("payInfoServiceImpl", payInfoServiceImpl);
			map.put("upload_id", parameter.uploadId);
			map.put("edpCompanyId", parameter.edpCompanyId);
			map.put("edpPlatformId", parameter.edpPlatformId);
			map.put("logisticId", parameter.logisticId);
			map.put("weightUnit", parameter.weightUnit);
			map.put("jcbPort", parameter.jcbPort);
			map.put("applyPort", parameter.applyPort);
			map.put("transferRegionInSp", parameter.transferRegionInSp);
			map.put("customerId", parameter.customerId);
			map.put("tbedpinfoMapper", tbedpinfoMapper);
			map.put("tblogisticinfoMapper", tblogisticinfoMapper);
			map.put("tbuploadinfoMapper", tbuploadinfoMapper);
			map.put("tbuploaddetailMapper", tbuploaddetailMapper);
			map.put("tbuploadDetailDao", tbuploadDetailDao);
			map.put("tbpayinfoMapper", tbpayinfoMapper);
			map.put("tborderheadMapper", tborderheadMapper);
			map.put("tborderlistMapper", tborderlistMapper);
			map.put("tbwaybillMapper", tbwaybillMapper);
			map.put("messageSender", messageSender);
			map.put("tbinventoryheadMapper", tbinventoryheadMapper);
			map.put("tbinventorybodyMapper", tbinventorybodyMapper);
			map.put("customerDao", customerDao);
			map.put("waybillServiceImpl", waybillServiceImpl);
			map.put("tbuploadinfoDao", tbuploadinfoDao);
			QuartzConfig.StartTask("send", "order", map);
		} catch (Exception e) {
			model.setIsError(true);
			model.setMessage(e.getMessage());
		}
		return model;
	}

	@ResponseBody
	@PostMapping("/GetUploadDetail")
	public PagerResponseModel DownloadUploadDetail(@RequestBody UploadQueryModel filter) {
		PagerResponseModel model = new PagerResponseModel();
		int pageIndex = filter.getPageIndex();
		int pageSize = filter.getPageSize();
		int upload_id = filter.getFilter().getUploadId();
		int startIndex = (pageIndex - 1) * pageSize;
		model.result = fetchDetails(upload_id, startIndex, pageSize);
		model.totalRows = fetchCount(upload_id);
		return model;
	}

	private int writeRowsToExcel(XSSFWorkbook wb, Sheet sheet, List<List<Object>> rows, int rowIndex) {
		int colIndex = 0;
		Font dataFont = wb.createFont();
		dataFont.setFontName("simsun");
		dataFont.setColor(IndexedColors.BLACK.index);
		XSSFCellStyle dataStyle = wb.createCellStyle();
		dataStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		dataStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
		dataStyle.setFont(dataFont);
		for (List<Object> rowData : rows) {
			Row dataRow = sheet.createRow(rowIndex);
			colIndex = 0;
			for (Object cellData : rowData) {
				Cell cell = dataRow.createCell(colIndex);
				if (cellData != null) {
					cell.setCellValue(cellData.toString());
				} else {
					cell.setCellValue("");
				}
				cell.setCellStyle(dataStyle);
				colIndex++;
			}
			rowIndex++;
		}
		return rowIndex;
	}

	@RequestMapping(value = "/downloadInvalidOrder", method = RequestMethod.GET)
	public void DownHscodeInvalidOrder(int uploadId, HttpServletResponse response) throws IOException {
		String fileName = "商品编码.xls";
		response.setHeader("content-Type", "application/vnd.ms-excel");
		// 下载文件的默认名称
		response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
		XSSFWorkbook wb = new XSSFWorkbook();
		try {
			// 查找所有商品HS编码不存在的订单
			try (Connection con = MyDao.getInstance().open()) {
				final String query = "SELECT  DISTINCT(declare_name) FROM upload_details WHERE upload_id = :upload_id and  hscode_ok=false";
				List<String> declare_names = con.createQuery(query).addParameter("upload_id", uploadId)
						.executeAndFetch(String.class);
			}
			wb.write(response.getOutputStream());
		} finally {
			wb.close();
		}
	}

	public List<Tbuploaddetail> fetchDetails(int upload_id, int start_index, int page_size) {

		try {
			List<Tbuploaddetail> details = tbuploadDetailDao.getUploadDetail(upload_id, start_index, page_size);
			return details;
		} catch (Exception e) {
			return null;
		}
	}

	public int fetchCount(int upload_id) {
		try {
			return tbuploadDetailDao.getCountOfDetail(upload_id);
		} catch (Exception e) {
			return 0;
		}
	}
}
